package com.dcjt.firehotcarpad.utils

import com.amap.api.location.AMapLocation
import com.cn.dcjt.chinafree.utils.ConvertUtils
import java.util.*
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt

object MessageUtil {
    private var pi = 3.1415926535897932384626
    private var x_pi = 3.14159265358979324 * 3000.0 / 180.0
    private var a = 6378245.0
    private var ee = 0.00669342162296594323
    fun getMessage(phone: String,location: AMapLocation): ByteArray {
        val buff = ByteArray(48)
        // 标识符
        buff[0] = 0x99.toByte()
        //消息头
        buff[1] = 0x99.toByte()
        buff[2] = 0x63.toByte()
        buff[3] = 0x10.toByte()
        buff[4] = 0
        buff[5] = 0x27.toByte()
        var id = phone
        while (id.length < 20) {
            id = "0$id"
        }
        var position = 6

        for (i in 0 until 20 step 2) {
            val strId = id.substring(i, i + 2)
            buff[position] = strId.toInt().toByte()
            position++
        }
        val array = gcj02_To_Gps84(
            ConvertUtils.saveDecimals(6, location.latitude),
            ConvertUtils.saveDecimals(6, location.longitude)
        )

        val x = doubleToByte(array!![0])
        val y = doubleToByte(array[1])


        for (b in y) {
            buff[position] = b
            position++
        }
        for (b in x) {
            buff[position] = b
            position++
        }

        // 补位 速度、方向、高度
//        for (i in 0 until 6) {
//            buff[position + i] = 0
//            position++
//        }
        //速度
        buff[32] = 0
        buff[33] = location.speed.toByte()
        //方向
        buff[34] = 0
        buff[35] = location.bearing.toByte()
        //高度
        buff[36] = 0
        buff[37] = location.altitude.toByte()
        val calendar = Calendar.getInstance()
        val years = ushortToBytes(calendar.get(Calendar.YEAR))
        buff[38] = years[0]
        buff[39] = years[1]
        buff[40] = (calendar.get(Calendar.MONTH) + 1).toByte()
        buff[41] = calendar.get(Calendar.DATE).toByte()
        buff[42] = calendar.get(Calendar.HOUR_OF_DAY).toByte()
        buff[43] = calendar.get(Calendar.MINUTE).toByte()
        buff[44] = calendar.get(Calendar.SECOND).toByte()
        buff[45] = 0x00.toByte()
        buff[46] = 0xAA.toByte()
        buff[47] = 0xAA.toByte()
        return buff
    }


    private fun doubleToByte(d: Double): ByteArray {
        val b = ByteArray(8)
        var l = java.lang.Double.doubleToLongBits(d)
        for (i in b.indices) {
            b[i] = l.toByte()
            l = l shr 8
        }
        return b
    }

    private fun ushortToBytes(n: Int): ByteArray {
        val b = ByteArray(2)
        b[1] = (n and 0xff).toByte()
        b[0] = (n shr 8 and 0xff).toByte()
        return b
    }

    /**
     * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
     */
    fun gcj02_To_Gps84(lat: Double, lon: Double): DoubleArray {
        val gps: DoubleArray = transform(lat, lon)
        return doubleArrayOf(lat * 2 - gps[0], lon * 2 - gps[1])
    }

    private fun transformLat(x: Double, y: Double): Double {
        var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(abs(x))
        ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0
        ret += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0
        ret += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0
        return ret
    }

    private fun transformLon(x: Double, y: Double): Double {
        var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(abs(x))
        ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0
        ret += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0
        ret += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0
        return ret
    }

    private fun transform(lat: Double, lon: Double): DoubleArray {
        if (outOfChina(lat, lon)) {
            return doubleArrayOf(lat, lon)
        }
        var dLat = transformLat(lon - 105.0, lat - 35.0)
        var dLon = transformLon(lon - 105.0, lat - 35.0)
        val radLat: Double = lat / 180.0 * pi
        var magic = sin(radLat)
        magic = 1 - ee * magic * magic
        val sqrtMagic = sqrt(magic)
        dLat = dLat * 180.0 / (a * (1 - ee) / (magic * sqrtMagic) * pi)
        dLon = dLon * 180.0 / (a / sqrtMagic * cos(radLat) * pi)
        val mgLat = lat + dLat
        val mgLon = lon + dLon
        return doubleArrayOf(mgLat, mgLon)
    }

    private fun outOfChina(lat: Double, lon: Double): Boolean {
        if (lon < 72.004 || lon > 137.8347) return true
        return lat < 0.8293 || lat > 55.8271
    }

    fun bytesToHexString(bArr: ByteArray): String {
        val sb = StringBuffer(bArr.size)
        var sTmp: String
        for (i in bArr.indices) {
            sTmp = Integer.toHexString(0xFF and bArr[i].toInt())
            if (sTmp.length < 2) sb.append(0)
            sb.append(sTmp.toUpperCase(Locale.ROOT))
        }
        return sb.toString()
    }
}